home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / DesktopDoubler / Nub / DesktopDoubler.c next >
Encoding:
C/C++ Source or Header  |  1999-06-26  |  8.5 KB  |  419 lines  |  [TEXT/CWIE]

  1. #define DISABLE_LOCAL_CALLTRACE        1        // Set to 1 to disable Call Traces for this file.
  2. #define DISABLE_LOCAL_DEBUG            0        // Set to 1 to disable all debugging for this file.
  3. #include "DebugUtils.h"
  4.  
  5. #include <Errors.h>
  6. #include <LowMem.h>
  7. #include "ContextUtils.h"
  8. #include "DisplayManager.h"
  9. #include "DesktopDoubler.h"
  10. #include "Nub.h"
  11. #include "PatchHarness.h"
  12. #include "ProcInfo.h"
  13.  
  14.  
  15.  
  16.  
  17.  
  18. #define DISPLAY_COUNT                2
  19.  
  20.  
  21.  
  22.  
  23.  
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27.  
  28. static OSStatus InitDisplayManager(UInt32 numVirtualDisplays);
  29. static void TermDisplayManager(void);
  30.  
  31. static pascal void DMFinalInitPatch(void);
  32. static pascal void GetMousePatch(Point *mouseLoc,GetMouseProcPtr getMouseProc);
  33. static pascal SInt32 MenuSelectPatch(Point startPt,MenuSelectProcPtr menuSelectProc);
  34. static pascal void SynchIdleTimePatch(void);
  35. static pascal void DMNotifier(AppleEvent *aevent);
  36. static void CheckForConfigChange(DisplayIDType displayID,AEDesc *oldConfig,AEDesc *newConfig);
  37.  
  38. #ifdef __cplusplus
  39. }
  40. #endif
  41.  
  42.  
  43.  
  44.  
  45.  
  46. #if GENERATINGPOWERPC
  47.     static RoutineDescriptor                gDMFinalInitPatchRD = BUILD_ROUTINE_DESCRIPTOR(uppDMFinalInitPatchProcInfo,DMFinalInitPatch);
  48.     static RoutineDescriptor                *gDMFinalInitPatchUPP = (RoutineDescriptor*)&gDMFinalInitPatchRD;
  49.     static RoutineDescriptor                gGetMousePatchRD = BUILD_ROUTINE_DESCRIPTOR(uppGetMousePatchProcInfo,GetMousePatch);
  50.     static RoutineDescriptor                *gGetMousePatchUPP = (RoutineDescriptor*)&gGetMousePatchRD;
  51.     static RoutineDescriptor                gMenuSelectPatchRD = BUILD_ROUTINE_DESCRIPTOR(uppMenuSelectPatchProcInfo,MenuSelectPatch);
  52.     static RoutineDescriptor                *gMenuSelectPatchUPP = (RoutineDescriptor*)&gMenuSelectPatchRD;
  53.     static RoutineDescriptor                gSynchIdleTimePatchRD = BUILD_ROUTINE_DESCRIPTOR(uppSynchIdleTimePatchProcInfo,SynchIdleTimePatch);
  54.     static RoutineDescriptor                *gSynchIdleTimePatchUPP = (RoutineDescriptor*)&gSynchIdleTimePatchRD;
  55.     static RoutineDescriptor                gDMNotifierRD = BUILD_ROUTINE_DESCRIPTOR(uppDMNotificationProcInfo,DMNotifier);
  56.     static RoutineDescriptor                *gDMNotifierUPP = (RoutineDescriptor*)&gDMNotifierRD;
  57. #else
  58.     static DMFinalInitPatchUPP                gDMFinalInitPatchUPP = DMFinalInitPatch;
  59.     static GetMousePatchUPP                    gGetMousePatchUPP = GetMousePatch;
  60.     static MenuSelectPatchUPP                gMenuSelectPatchUPP = MenuSelectPatch;
  61.     static SynchIdleTimePatchUPP            gSynchIdleTimePatchUPP = SynchIdleTimePatch;
  62.     static DMNotificationUPP                gDMNotifierUPP = DMNotifier;
  63. #endif
  64.  
  65.  
  66. extern NubInfo                                *gInfo;
  67. DisplayManager                                *gDMan = NULL;
  68.  
  69.  
  70.  
  71.  
  72.  
  73. OSStatus InitDesktopDoubler(void)
  74. {
  75.     OSStatus    err;
  76.     
  77.     
  78.     // Install patches.
  79.     err = InstallPatch(gInfo->patchList,'DMFI',(UniversalProcPtr)gDMFinalInitPatchUPP);
  80.     if (err != noErr)
  81.     {
  82.         dprintf(kDConPrefix "InstallPatch _DisplayManager failed: %ld\n",err);
  83.         return err;
  84.     }
  85.     
  86.     err = InstallPatch(gInfo->patchList,'DMNt',(UniversalProcPtr)gDMNotifierUPP);
  87.     if (err != noErr)
  88.     {
  89.         dprintf(kDConPrefix "InstallPatch DMNotifer failed: %ld\n",err);
  90.         return err;
  91.     }
  92.     
  93.     err = InstallPatch(gInfo->patchList,'GetM',(UniversalProcPtr)gGetMousePatchUPP);
  94.     if (err != noErr)
  95.     {
  96.         dprintf(kDConPrefix "InstallPatch _GetMouse failed: %ld\n",err);
  97.         return err;
  98.     }
  99.     
  100.     err = InstallPatch(gInfo->patchList,'MenS',(UniversalProcPtr)gMenuSelectPatchUPP);
  101.     if (err != noErr)
  102.     {
  103.         dprintf(kDConPrefix "InstallPatch _MenuSelect failed: %ld\n",err);
  104.         return err;
  105.     }
  106.     
  107.     err = InstallPatch(gInfo->patchList,'IDLE',(UniversalProcPtr)gSynchIdleTimePatchUPP);
  108.     if (err != noErr)
  109.     {
  110.         dprintf(kDConPrefix "InstallPatch _SynchIdleTime failed: %ld\n",err);
  111.         return err;
  112.     }
  113.     
  114.     #if APPBUILD
  115.         err = InitDisplayManager(DISPLAY_COUNT);
  116.         if (err != noErr)
  117.         {
  118.             dprintf(kDConPrefix "InitDisplayManager failed: %ld\n",err);
  119.             return err;
  120.         }
  121.     #endif
  122.     
  123.     return noErr;
  124. }
  125.  
  126.  
  127.  
  128.  
  129.  
  130. void TermDesktopDoubler(void)
  131. {
  132.     // Remove patches.
  133.     RemovePatch(gInfo->patchList,'IDLE');
  134.     RemovePatch(gInfo->patchList,'MenS');
  135.     RemovePatch(gInfo->patchList,'GetM');
  136.     RemovePatch(gInfo->patchList,'DMNt');
  137.     RemovePatch(gInfo->patchList,'DMFI');
  138.     
  139.     // Remove virtual displays.
  140.     TermDisplayManager();
  141. }
  142.  
  143.  
  144.  
  145.  
  146.  
  147. OSStatus InitDisplayManager(UInt32 numVirtualDisplays)
  148. {
  149.     OSStatus    err;
  150.     
  151.     
  152.     gDMan = new DisplayManager();
  153.     dAssert(gDMan != NULL);
  154.     if (gDMan == NULL)
  155.         return memFullErr;
  156.     
  157.     err = gDMan->Initialize(numVirtualDisplays);
  158.     if (err != noErr)
  159.     {
  160.         delete gDMan;
  161.         gDMan = NULL;
  162.         return err;
  163.     }
  164.     
  165.     return noErr;
  166. }
  167.  
  168.  
  169.  
  170.  
  171.  
  172. void TermDisplayManager(void)
  173. {
  174.     if (gDMan != NULL)
  175.     {
  176.         delete gDMan;
  177.         gDMan = NULL;
  178.     }
  179. }
  180.  
  181.  
  182. #if 0
  183. #pragma mark -
  184. #endif
  185.  
  186.  
  187. pascal void DMFinalInitPatch(void)
  188. {
  189.     GlobalContext    globals;
  190.     OSStatus        err;
  191.     
  192.     
  193.     // Only do this once.
  194.     if (gDMan != NULL)
  195.         return;
  196.     
  197.     if (true)
  198.     {
  199.         THzContext        zone(SystemZone());
  200.         
  201.         err = InitDisplayManager(DISPLAY_COUNT);
  202.         if (err != noErr)
  203.             dprintf(kDConPrefix "InitDisplayManager failed: %ld\n",err);
  204.     }
  205. }
  206.  
  207.  
  208.  
  209.  
  210.  
  211. pascal void GetMousePatch(Point *mouseLoc,GetMouseProcPtr getMouseProc)
  212. {
  213.     CallGetMouseProc(getMouseProc,mouseLoc);
  214.     if (true)
  215.     {
  216.         GlobalContext    globals;
  217.         
  218.         gDMan->OffsetMBarMouse(mouseLoc);
  219.     }
  220. }
  221.  
  222.  
  223.  
  224.  
  225.  
  226. pascal SInt32 MenuSelectPatch(Point startPt,MenuSelectProcPtr menuSelectProc)
  227. {
  228.     SInt32    result;
  229.     
  230.     
  231.     if (true)
  232.     {
  233.         GlobalContext    globals;
  234.         
  235.         gDMan->SetMBarTracker(LMGetMouseLocation(),true);
  236.     }
  237.     
  238.     result = CallMenuSelectProc(menuSelectProc,startPt);
  239.     
  240.     if (true)
  241.     {
  242.         GlobalContext    globals;
  243.         
  244.         gDMan->SetMBarTracker(LMGetMouseLocation(),false);
  245.     }
  246.     
  247.     return result;
  248. }
  249.  
  250.  
  251.  
  252.  
  253.  
  254. pascal void SynchIdleTimePatch(void)
  255. {
  256.     static Boolean    reentered = false;
  257.     
  258.     
  259.     // Sanity checks.
  260.     if (reentered || (gDMan == NULL))
  261.         return;
  262.     
  263.     if (true)
  264.     {
  265.         THzContext        zone(SystemZone());
  266.         
  267.         reentered = true;
  268.         gDMan->Idle(LMGetMouseLocation());
  269.         reentered = false;
  270.     }
  271. }
  272.  
  273.  
  274.  
  275.  
  276.  
  277. pascal void DMNotifier(AppleEvent *aevent)
  278. {
  279.     GlobalContext    globals;
  280.     DescType        actualType;
  281.     Size            actualSize;
  282.     AEEventClass    eventClass;
  283.     AEEventID        eventID;
  284.     AEDesc            displayNoticeDesc;
  285.     AEDesc            displayDesc;
  286.     AEDesc            oldConfigDesc;
  287.     AEDesc            newConfigDesc;
  288.     long            numDisplays,index;
  289.     DisplayIDType    displayID;
  290.     OSStatus        err;
  291.     
  292.     
  293.     // Verify this event is what were expecting
  294.     actualSize = sizeof(AEEventClass);
  295.     err = AEGetAttributePtr(aevent,
  296.                             keyEventClassAttr,
  297.                             typeType,
  298.                             &actualType,
  299.                             (Ptr)&eventClass,
  300.                             sizeof(AEEventClass),
  301.                             &actualSize);
  302.     if (err || (eventClass != kCoreEventClass))
  303.         return;
  304.     
  305.     actualSize = sizeof(AEEventID);
  306.     err = AEGetAttributePtr(aevent,
  307.                             keyEventIDAttr,
  308.                             typeType,
  309.                             &actualType,
  310.                             (Ptr)&eventID,
  311.                             sizeof(AEEventID),
  312.                             &actualSize);
  313.     if (err || (eventID != kAESystemConfigNotice))
  314.         return;
  315.     
  316.     // Get the display notice record
  317.     err = AEGetParamDesc(    aevent,
  318.                             kAEDisplayNotice,
  319.                             typeAERecord,
  320.                             &displayNoticeDesc);
  321.     if (err != noErr)
  322.         return;
  323.     
  324.     // Iterate thru each display in record
  325.     AECountItems(&displayNoticeDesc,&numDisplays);
  326.     for (index = 1;index <= numDisplays;index++)
  327.     {
  328.         err = AEGetNthDesc(    &displayNoticeDesc,
  329.                             index,
  330.                             typeAERecord,
  331.                             (AEKeyword*)&displayID,
  332.                             &displayDesc);
  333.         if (err == noErr)
  334.         {
  335.             // Get old config and new config
  336.             err = AEGetParamDesc(    &displayDesc,
  337.                                     keyDisplayOldConfig,
  338.                                     typeAERecord,
  339.                                     &oldConfigDesc);
  340.             if (err == noErr)
  341.             {
  342.                 err = AEGetParamDesc(    &displayDesc,
  343.                                         keyDisplayNewConfig,
  344.                                         typeAERecord,
  345.                                         &newConfigDesc);
  346.                 if (err == noErr)
  347.                 {
  348.                     // Call handler with old and new configs
  349.                     CheckForConfigChange(displayID,&oldConfigDesc,&newConfigDesc);
  350.                     
  351.                     AEDisposeDesc(&newConfigDesc);
  352.                 }
  353.                 
  354.                 AEDisposeDesc(&oldConfigDesc);
  355.             }
  356.             
  357.             AEDisposeDesc(&displayDesc);
  358.         }
  359.     }
  360.     
  361.     AEDisposeDesc(&displayNoticeDesc);
  362. }
  363.  
  364.  
  365.  
  366.  
  367.  
  368. void CheckForConfigChange(DisplayIDType displayID,AEDesc *oldConfig,AEDesc *newConfig)
  369. {
  370.     Display        *display;
  371.     Rect        oldGDRect,newGDRect;
  372.     DescType    actualType;
  373.     Size        actualSize;
  374.     Boolean        changed = false;
  375.     OSStatus    err;
  376.     
  377.     
  378.     // Make sure we've got what we need to
  379.     // actually process a config change
  380.     if (gDMan == NULL)
  381.         return;
  382.     
  383.     display = gDMan->FindDisplay(displayID);
  384.     if (display == NULL)
  385.         return;
  386.     
  387.     // Check for moved display
  388.     actualSize = sizeof(Rect);
  389.     err = AEGetParamPtr(oldConfig,
  390.                         keyDeviceRect,
  391.                         typeQDRectangle,
  392.                         &actualType,
  393.                         (Ptr)&oldGDRect,
  394.                         sizeof(Rect),
  395.                         &actualSize);
  396.     if (err == noErr)
  397.     {
  398.         actualSize = sizeof(Rect);
  399.         err = AEGetParamPtr(newConfig,
  400.                             keyDeviceRect,
  401.                             typeQDRectangle,
  402.                             &actualType,
  403.                             (Ptr)&newGDRect,
  404.                             sizeof(Rect),
  405.                             &actualSize);
  406.         if (err == noErr)
  407.         {
  408.             if ((oldGDRect.top != newGDRect.top) || (oldGDRect.left != newGDRect.left))
  409.             {
  410.                 display->MoveTo(newGDRect.left,newGDRect.top);
  411.                 changed = true;
  412.             }
  413.         }
  414.     }
  415.     
  416.     if (changed)
  417.         gDMan->Refresh();
  418. }
  419.